#ifndef AUXILIARTYPES
#define AUXILIARTYPES

//AVL data structure + auxiliary data
#include "AVL.h"
//#include "auxiliary.h"

#include "core/gui/opengl/scene/scene.h"
#include "core/gui/opengl/glwindow.h"

using namespace std;

typedef std::vector<int> Cluster;

struct Edge;

/**
 * Auxiliary structure for edges
 */
typedef struct Edge {
	//index of faces
	int f0;
	int f1;

	//index of vertices
	int v0;
	int v1;

#ifdef SAVEIMAGE
	//projected points (for simplicity)
	vcg::Point2d proj0;
	vcg::Point2d proj1;
#endif

	double qual;
	double geod;
	double length;
	double angle;
	double weight;
	int density;

	//boolean operators

	bool operator < ( const struct Edge& ep ) const {
		if ( qual == ep.qual ) {
			if ( min(f0, f1) == min(ep.f0, ep.f1) ) {
				return ( max(f0, f1) < max(ep.f0, ep.f1) );
			}
			else return ( min(f0, f1) < min(ep.f0, ep.f1) );
		}
		else return qual < ep.qual;
	}

	bool operator > ( const struct Edge& ep ) const {
		if ( qual == ep.qual ) {
			if ( min(f0, f1) == min(ep.f0, ep.f1) ) {
				return ( max(f0, f1) > max(ep.f0, ep.f1) );
			}
			else return ( min(f0, f1) > min(ep.f0, ep.f1) );
		}
		else return qual > ep.qual;
	}

	bool operator == ( const struct Edge& ep ) const {
		return ( min(f0,f1) == min(ep.f0, ep.f1) && max(f0,f1) == max(ep.f0, ep.f1) );
	}

} Edge;

/**
 * Edge references
 */
typedef struct {
	int edges[3];		//stores three indices, one for each edge of the corresponding face
} EdgeReferences;

/**
 * Class for comparison of vertices based on their quality
 */
class CompareVertices
{
public:
	CompareVertices(CGMesh& mesh) : _mesh(mesh) {};
	bool operator () (int i, int j) { return _mesh.vert[i].Q() < _mesh.vert[j].Q(); }

private:
	CGMesh& _mesh;
};


/**
 * Class EdgePair
 * Contains a pair of edge indices and the index of the vertex that the edges share.
 */
class EdgePair {

public: 

	std::pair<int, int> edges;
	int sharedVertex;
	double qual;

	EdgePair() {};

	EdgePair( int e0, int e1, int v ) {
		edges.first = e0;
		edges.second = e1;
		sharedVertex = v;
	}

	static int findSharedVertex( Edge e0, Edge e1 ) {
		if ( e0.v0 == e1.v0 ) return e0.v0;
		if ( e0.v1 == e1.v0 ) return e0.v1;
		if ( e0.v0 == e1.v1 ) return e0.v0;
		if ( e0.v1 == e1.v1 ) return e0.v1;
		assert(0);	//should never get into here
		return -1;
	}

	int getSharedVertex() { return sharedVertex; }

	std::pair<int, int> getEdges() { return edges; }

	void setQual( double q ) { qual = q; }

	double getQual() { return qual; }

	bool operator < ( const EdgePair& ep ) const {
		if ( min(edges.first, edges.second) == min (ep.edges.first, ep.edges.second) ) {
			return max(edges.first, edges.second) < max(ep.edges.first, ep.edges.second);
		}
		else return min(edges.first, edges.second) < min(ep.edges.first, ep.edges.second);
	}

	bool operator > ( const EdgePair& ep ) const {
		if ( min(edges.first, edges.second) == min (ep.edges.first, ep.edges.second) ) {
			return max(edges.first, edges.second) > max(ep.edges.first, ep.edges.second);
		}
		else return min(edges.first, edges.second) > min(ep.edges.first, ep.edges.second);
	}

	bool operator == ( const EdgePair& ep ) const {
		return ( min(edges.first, edges.second) == min (ep.edges.first, ep.edges.second) ) && ( max(edges.first, edges.second) == max (ep.edges.first, ep.edges.second) );
	}
};


//Contour is defined as set of triples
typedef AVLTree<EdgePair> Contour;


/**
 * Each boundary is made of edges, and keeps track of faces that are adjacent to region A and region B. Same region A can be also adjacent
 * to region C, D and so on, so we'll have different boundaries for each adjacency. For each pair of adjacent regions, we'll have a set of edges
 * (the Boundary) and a pair in the conflict list (the Conflict). The i-th Boundary corresponds to the i-th Conflict of the list.
 **/
typedef std::set<int>			Boundary;		//boundary represented as set of unique edges
typedef std::pair<int,int>		Conflict;		//A conflict is made of two adjacante regions
typedef std::vector< Conflict > ConflictList;	//Conflict list

typedef struct {
	double boundary;
	double cluster0;
	double cluster1;
	int bn;
	int c0n;
	int c1n;
} BoundaryInfo;


typedef enum { sum, mean, maxq, variance } QualityMeasure;
typedef enum { none, expw, lin } WeightType;
typedef enum { signficant = 0, notsignificant, numtypes } VertexType;

#endif //AUXILIARTYPES
